#include "gateway_server.h"

#include "gateway.pb.h"
#include "log.h"
#include "notify.pb.h"
#include "uuid.h"

namespace chat {
// GatewayServer

void GatewayServer::openHandler(websocketpp::connection_hdl hdl) {
    LOG_INFO("[{}]长连接建立",
             static_cast<void*>(ws_server_->get_con_from_hdl(hdl).get()));
}

void GatewayServer::closeHandler(websocketpp::connection_hdl hdl) {
    server_t::connection_ptr conn = ws_server_->get_con_from_hdl(hdl);
    if (conn) {
        // 1. 获取该长连接对应的客户端信息
        ClientPtr client = connections_.client(conn);
        if (client) {
            // 2. 从会话管理中删除该用户的登录会话, 状态信息
            redis_session_->remove(client->session_id);
            redis_status_->remove(client->user_id);

            // 3. 删除长连接管理
            connections_.remove(conn);

            LOG_DEBUG("[{}]长连接断开, 清除缓存数据[{}-{}]",
                      static_cast<void*>(conn.get()), client->user_id,
                      client->session_id);
        } else {
            LOG_WARN("[{}]长连接断开，未找到长连接对应的客户端信息!",
                     static_cast<void*>(conn.get()));
        }
    }
}

void GatewayServer::messageHandler(server_t* server,
                                   websocketpp::connection_hdl hdl,
                                   server_t::message_ptr msg) {
    // 1. 获取有效消息在和数据，并进行反序列化
    std::string body = msg->get_payload();
    ClientAuthenticationReq request;
    if (!request.ParseFromString(body)) {
        LOG_ERROR("消息正文反序列化失败");

        ws_server_->close(hdl, websocketpp::close::status::unsupported_data,
                          "正文反序列化失败!");
        return;
    }

    // 2. 提取请求中的 request_id和session_id
    const std::string& request_id = request.request_id();
    const std::string& session_id = request.session_id();

    // 3. 从会话管理中获取当前登录会话对应的user_id
    auto user_id = redis_session_->uid(session_id);
    if (!user_id) {
        LOG_ERROR("会话管理中未找到当前登录会话对应的user_id");
        ws_server_->close(hdl, websocketpp::close::status::unsupported_data,
                          "会话管理中未找到当前登录会话对应的user_id!");
        return;
    }

    // 4. 将客户端信息和长连接进行管理
    server_t::connection_ptr conn = server->get_con_from_hdl(hdl);
    connections_.insert(conn, std::make_shared<Client>(*user_id, session_id));
    LOG_DEBUG("新增长连接管理[{}]: {}-{}", static_cast<void*>(conn.get()),
              *user_id, session_id);
}

void GatewayServer::initHttpServer() {
    http_server_->Post(GET_PHONE_VERIFY_CODE_PATH,
                       static_cast<httplib::Server::Handler>(std::bind(
                           &GatewayServer::handleGetPhoneVerifyCode, this,
                           std::placeholders::_1, std::placeholders::_2)));
    http_server_->Post(USERNAME_REGISTER_PATH,
                       static_cast<httplib::Server::Handler>(std::bind(
                           &GatewayServer::handleUsernameRegister, this,
                           std::placeholders::_1, std::placeholders::_2)));
    http_server_->Post(USERNAME_LOGIN_PATH,
                       static_cast<httplib::Server::Handler>(std::bind(
                           &GatewayServer::handleUsernameLogin, this,
                           std::placeholders::_1, std::placeholders::_2)));
    http_server_->Post(PHONE_REGISTER_PATH,
                       static_cast<httplib::Server::Handler>(std::bind(
                           &GatewayServer::handlePhoneRegister, this,
                           std::placeholders::_1, std::placeholders::_2)));
    http_server_->Post(PHONE_LOGIN_PATH,
                       static_cast<httplib::Server::Handler>(std::bind(
                           &GatewayServer::handlePhoneLogin, this,
                           std::placeholders::_1, std::placeholders::_2)));
    http_server_->Post(GET_USER_INFO_PATH,
                       static_cast<httplib::Server::Handler>(std::bind(
                           &GatewayServer::handleGetUserInfo, this,
                           std::placeholders::_1, std::placeholders::_2)));
    http_server_->Post(SET_AVATAR_PATH,
                       static_cast<httplib::Server::Handler>(std::bind(
                           &GatewayServer::handleSetAvatar, this,
                           std::placeholders::_1, std::placeholders::_2)));
    http_server_->Post(SET_NICKNAME_PATH,
                       static_cast<httplib::Server::Handler>(std::bind(
                           &GatewayServer::handleSetNickname, this,
                           std::placeholders::_1, std::placeholders::_2)));
    http_server_->Post(SET_DESCRIPTION_PATH,
                       static_cast<httplib::Server::Handler>(std::bind(
                           &GatewayServer::handleSetDescription, this,
                           std::placeholders::_1, std::placeholders::_2)));
    http_server_->Post(SET_PHONE_PATH,
                       static_cast<httplib::Server::Handler>(std::bind(
                           &GatewayServer::handleSetPhone, this,
                           std::placeholders::_1, std::placeholders::_2)));

    http_server_->Post(GET_FRIEND_LIST_PATH,
                       static_cast<httplib::Server::Handler>(std::bind(
                           &GatewayServer::handleGetFriendList, this,
                           std::placeholders::_1, std::placeholders::_2)));
    http_server_->Post(ADD_FRIEND_APPLY_PATH,
                       static_cast<httplib::Server::Handler>(std::bind(
                           &GatewayServer::handleAddFriend, this,
                           std::placeholders::_1, std::placeholders::_2)));
    http_server_->Post(ADD_FRIEND_PROCESS_PATH,
                       static_cast<httplib::Server::Handler>(std::bind(
                           &GatewayServer::handleAddFriendProcess, this,
                           std::placeholders::_1, std::placeholders::_2)));
    http_server_->Post(REMOVE_FRIEND_PATH,
                       static_cast<httplib::Server::Handler>(std::bind(
                           &GatewayServer::handleRemoveFriend, this,
                           std::placeholders::_1, std::placeholders::_2)));
    http_server_->Post(SEARCH_FRIEND_PATH,
                       static_cast<httplib::Server::Handler>(std::bind(
                           &GatewayServer::handleSearchFriend, this,
                           std::placeholders::_1, std::placeholders::_2)));
    http_server_->Post(GET_CHAT_SESSION_LIST_PATH,
                       static_cast<httplib::Server::Handler>(std::bind(
                           &GatewayServer::handleGetChatSessionList, this,
                           std::placeholders::_1, std::placeholders::_2)));
    http_server_->Post(CREATE_CHAT_SESSION_PATH,
                       static_cast<httplib::Server::Handler>(std::bind(
                           &GatewayServer::handleCreateChatSession, this,
                           std::placeholders::_1, std::placeholders::_2)));
    http_server_->Post(GET_CHAT_SESSION_MEMBER_PATH,
                       static_cast<httplib::Server::Handler>(std::bind(
                           &GatewayServer::handleGetChatSessionMember, this,
                           std::placeholders::_1, std::placeholders::_2)));
    http_server_->Post(GET_PENDING_FRIEND_EVENTS_PATH,
                       static_cast<httplib::Server::Handler>(std::bind(
                           &GatewayServer::handleGetPendingFriendEvents, this,
                           std::placeholders::_1, std::placeholders::_2)));

    http_server_->Post(GET_MESSAGE_STORAGE_HISTORY_PATH,
                       static_cast<httplib::Server::Handler>(std::bind(
                           &GatewayServer::handleGetMessageStorageHistory, this,
                           std::placeholders::_1, std::placeholders::_2)));
    http_server_->Post(GET_MESSAGE_STORAGE_RECENT_PATH,
                       static_cast<httplib::Server::Handler>(std::bind(
                           &GatewayServer::handleGetMessageStorageRecent, this,
                           std::placeholders::_1, std::placeholders::_2)));
    http_server_->Post(
        SEARCH_MESSAGE_STORAGE_HISTORY_PATH,
        static_cast<httplib::Server::Handler>(
            std::bind(&GatewayServer::handleSearchMessageStorageHistory, this,
                      std::placeholders::_1, std::placeholders::_2)));

    http_server_->Post(GET_SINGLE_FILE_PATH,
                       static_cast<httplib::Server::Handler>(std::bind(
                           &GatewayServer::handleGetSingleFile, this,
                           std::placeholders::_1, std::placeholders::_2)));
    http_server_->Post(GET_MULTI_FILE_PATH,
                       static_cast<httplib::Server::Handler>(std::bind(
                           &GatewayServer::handleGetMultiFile, this,
                           std::placeholders::_1, std::placeholders::_2)));
    http_server_->Post(PUT_SINGLE_FILE_PATH,
                       static_cast<httplib::Server::Handler>(std::bind(
                           &GatewayServer::handlePutSingleFile, this,
                           std::placeholders::_1, std::placeholders::_2)));
    http_server_->Post(PUT_MULTI_FILE_PATH,
                       static_cast<httplib::Server::Handler>(std::bind(
                           &GatewayServer::handlePutMultiFile, this,
                           std::placeholders::_1, std::placeholders::_2)));

    http_server_->Post(SPEECH_RECOGNITION_PATH,
                       static_cast<httplib::Server::Handler>(std::bind(
                           &GatewayServer::handleSpeechRecognition, this,
                           std::placeholders::_1, std::placeholders::_2)));

    http_server_->Post(NEW_MESSAGE_PATH,
                       static_cast<httplib::Server::Handler>(std::bind(
                           &GatewayServer::handleNewMessage, this,
                           std::placeholders::_1, std::placeholders::_2)));
}
void GatewayServer::initWebSocketServer(uint16_t ws_port) {
    // 2. 初始化日志输出 - 关闭日志输出
    ws_server_->set_access_channels(websocketpp::log::alevel::none);

    // 3. 初始化 asio 框架
    ws_server_->init_asio();

    // 4. 设置消息处理/连接握手成功/连接关闭回调函数
    ws_server_->set_open_handler(
        std::bind(&GatewayServer::openHandler, this, std::placeholders::_1));
    ws_server_->set_close_handler(
        std::bind(&GatewayServer::closeHandler, this, std::placeholders::_1));
    auto message_handler =
        std::bind(&GatewayServer::messageHandler, this, ws_server_.get(),
                  std::placeholders::_1, std::placeholders::_2);
    ws_server_->set_message_handler(message_handler);

    // 5. 启用地址复用
    ws_server_->set_reuse_addr(true);

    // 6. 设置监听端口
    ws_server_->listen(ws_port);

    // 7. 开始监听
    ws_server_->start_accept();
}

void GatewayServer::handleGetPhoneVerifyCode(const httplib::Request& request,
                                             httplib::Response& response) {
    PhoneVerifyCodeReq req;
    PhoneVerifyCodeRsp rsp;

    do {
        // 1. 解析请求参数
        std::string body = request.body;
        if (!req.ParseFromString(body)) {
            LOG_ERROR("获取手机验证码请求反序列化失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取手机验证码请求反序列化失败");

            break;
        }

        // 2. 进行RPC调用
        auto channel =
            service_manager_->choose(user_service_name_);  // 获取通信信道
        if (channel == nullptr) {
            LOG_ERROR("获取用户服务通信信道失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取用户服务通信信道失败");

            break;
        }

        brpc::Controller cntl;
        chat::UserService_Stub stub(channel.get());
        stub.GetPhoneVerifyCode(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed()) {
            LOG_ERROR("获取手机验证码RPC调用失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取手机验证码RPC调用失败");

            break;
        }
    } while (0);

    response.set_content(rsp.SerializeAsString(), "application/x-probuf");
}

void GatewayServer::handleUsernameRegister(const httplib::Request& request,
                                           httplib::Response& response) {
    UserRegisterReq req;
    UserRegisterRsp rsp;

    do {
        // 1. 解析请求参数
        std::string body = request.body;
        if (!req.ParseFromString(body)) {
            LOG_ERROR("用户注册请求反序列化失败");
            rsp.set_success(false);
            rsp.set_errmsg("用户注册请求反序列化失败");

            break;
        }

        // 2. 进行RPC调用
        auto channel =
            service_manager_->choose(user_service_name_);  // 获取通信信道
        if (channel == nullptr) {
            LOG_ERROR("获取用户服务通信信道失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取用户服务通信信道失败");

            break;
        }

        brpc::Controller cntl;
        chat::UserService_Stub stub(channel.get());
        stub.UserRegister(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed()) {
            LOG_ERROR("用户注册RPC调用失败");
            rsp.set_success(false);
            rsp.set_errmsg("用户注册RPC调用失败");

            break;
        }
    } while (0);

    response.set_content(rsp.SerializeAsString(), "application/x-probuf");
}
void GatewayServer::handleUsernameLogin(const httplib::Request& request,
                                        httplib::Response& response) {
    UserLoginReq req;
    UserLoginRsp rsp;

    do {
        // 1. 解析请求参数
        std::string body = request.body;
        if (!req.ParseFromString(body)) {
            LOG_ERROR("用户登录请求反序列化失败");
            rsp.set_success(false);
            rsp.set_errmsg("用户登录请求反序列化失败");

            break;
        }

        // 2. 进行RPC调用
        auto channel =
            service_manager_->choose(user_service_name_);  // 获取通信信道
        if (channel == nullptr) {
            LOG_ERROR("获取用户服务通信信道失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取用户服务通信信道失败");

            break;
        }

        brpc::Controller cntl;
        chat::UserService_Stub stub(channel.get());
        stub.UserLogin(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed()) {
            LOG_ERROR("用户登录RPC调用失败");
            rsp.set_success(false);
            rsp.set_errmsg("用户登录RPC调用失败");

            break;
        }
    } while (0);

    response.set_content(rsp.SerializeAsString(), "application/x-probuf");
}

void GatewayServer::handlePhoneRegister(const httplib::Request& request,
                                        httplib::Response& response) {
    PhoneRegisterReq req;
    PhoneRegisterRsp rsp;

    do {
        // 1. 解析请求参数
        std::string body = request.body;
        if (!req.ParseFromString(body)) {
            LOG_ERROR("手机号注册请求反序列化失败");
            rsp.set_success(false);
            rsp.set_errmsg("手机号注册请求反序列化失败");

            break;
        }

        // 2. 进行RPC调用
        auto channel =
            service_manager_->choose(user_service_name_);  // 获取通信信道
        if (channel == nullptr) {
            LOG_ERROR("获取用户服务通信信道失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取用户服务通信信道失败");

            break;
        }

        brpc::Controller cntl;
        chat::UserService_Stub stub(channel.get());
        stub.PhoneRegister(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed()) {
            LOG_ERROR("手机号注册RPC调用失败");
            rsp.set_success(false);
            rsp.set_errmsg("手机号注册RPC调用失败");

            break;
        }
    } while (0);

    response.set_content(rsp.SerializeAsString(), "application/x-probuf");
}

void GatewayServer::handlePhoneLogin(const httplib::Request& request,
                                     httplib::Response& response) {
    PhoneLoginReq req;
    PhoneLoginRsp rsp;

    do {
        // 1. 解析请求参数
        std::string body = request.body;
        if (!req.ParseFromString(body)) {
            LOG_ERROR("手机号登录请求反序列化失败");
            rsp.set_success(false);
            rsp.set_errmsg("手机号登录请求反序列化失败");

            break;
        }

        // 2. 进行RPC调用
        auto channel =
            service_manager_->choose(user_service_name_);  // 获取通信信道
        if (channel == nullptr) {
            LOG_ERROR("获取用户服务通信信道失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取用户服务通信信道失败");

            break;
        }

        brpc::Controller cntl;
        chat::UserService_Stub stub(channel.get());
        stub.PhoneLogin(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed()) {
            LOG_ERROR("手机号登录RPC调用失败");
            rsp.set_success(false);
            rsp.set_errmsg("手机号登录RPC调用失败");

            break;
        }
    } while (0);

    response.set_content(rsp.SerializeAsString(), "application/x-probuf");
}

void GatewayServer::handleGetUserInfo(const httplib::Request& request,
                                      httplib::Response& response) {
    GetUserInfoReq req;
    GetUserInfoRsp rsp;

    do {
        // 1. 解析请求参数
        std::string body = request.body;
        if (!req.ParseFromString(body)) {
            LOG_ERROR("获取用户信息请求反序列化失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取用户信息请求反序列化失败");

            break;
        }

        // 2. 查看会话信息是否存在
        const std::string& session_id = req.session_id();
        auto user_id = redis_session_->uid(session_id);
        if (!user_id) {
            LOG_ERROR("[{}] 会话信息不存在", session_id);
            rsp.set_success(false);
            rsp.set_errmsg("会话信息不存在");

            break;
        }
        req.set_user_id(*user_id);

        // 2. 进行RPC调用
        auto channel =
            service_manager_->choose(user_service_name_);  // 获取通信信道
        if (channel == nullptr) {
            LOG_ERROR("获取用户服务通信信道失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取用户服务通信信道失败");

            break;
        }

        brpc::Controller cntl;
        chat::UserService_Stub stub(channel.get());
        stub.GetUserInfo(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed()) {
            LOG_ERROR("获取用户信息RPC调用失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取用户信息RPC调用失败");

            break;
        }
    } while (0);

    response.set_content(rsp.SerializeAsString(), "application/x-probuf");
}

void GatewayServer::handleSetAvatar(const httplib::Request& request,
                                    httplib::Response& response) {
    SetUserAvatarReq req;
    SetUserAvatarRsp rsp;

    do {
        // 1. 解析请求参数
        std::string body = request.body;
        if (!req.ParseFromString(body)) {
            LOG_ERROR("设置用户头像请求反序列化失败");
            rsp.set_success(false);
            rsp.set_errmsg("设置用户头像请求反序列化失败");

            break;
        }

        // 2. 查看会话信息是否存在
        const std::string& session_id = req.session_id();
        auto user_id = redis_session_->uid(session_id);
        if (!user_id) {
            LOG_ERROR("[{}] 会话信息不存在", session_id);
            rsp.set_success(false);
            rsp.set_errmsg("会话信息不存在");

            break;
        }
        req.set_user_id(*user_id);

        // 2. 进行RPC调用
        auto channel =
            service_manager_->choose(user_service_name_);  // 获取通信信道
        if (channel == nullptr) {
            LOG_ERROR("获取用户服务通信信道失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取用户服务通信信道失败");

            break;
        }

        brpc::Controller cntl;
        chat::UserService_Stub stub(channel.get());
        stub.SetUserAvatar(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed()) {
            LOG_ERROR("设置用户头像RPC调用失败");
            rsp.set_success(false);
            rsp.set_errmsg("设置用户头像RPC调用失败");

            break;
        }
    } while (0);

    response.set_content(rsp.SerializeAsString(), "application/x-probuf");
}

void GatewayServer::handleSetNickname(const httplib::Request& request,
                                      httplib::Response& response) {
    SetUserNicknameReq req;
    SetUserNicknameRsp rsp;

    do {
        // 1. 解析请求参数
        std::string body = request.body;
        if (!req.ParseFromString(body)) {
            LOG_ERROR("设置用户昵称请求反序列化失败");
            rsp.set_success(false);
            rsp.set_errmsg("设置用户昵称请求反序列化失败");

            break;
        }

        // 2. 查看会话信息是否存在
        const std::string& session_id = req.session_id();
        auto user_id = redis_session_->uid(session_id);
        if (!user_id) {
            LOG_ERROR("[{}] 会话信息不存在", session_id);
            rsp.set_success(false);
            rsp.set_errmsg("会话信息不存在");

            break;
        }
        req.set_user_id(*user_id);

        // 2. 进行RPC调用
        auto channel =
            service_manager_->choose(user_service_name_);  // 获取通信信道
        if (channel == nullptr) {
            LOG_ERROR("获取用户服务通信信道失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取用户服务通信信道失败");

            break;
        }

        brpc::Controller cntl;
        chat::UserService_Stub stub(channel.get());
        stub.SetUserNickname(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed()) {
            LOG_ERROR("设置用户昵称RPC调用失败");
            rsp.set_success(false);
            rsp.set_errmsg("设置用户昵称RPC调用失败");

            break;
        }
    } while (0);

    response.set_content(rsp.SerializeAsString(), "application/x-probuf");
}

void GatewayServer::handleSetDescription(const httplib::Request& request,
                                         httplib::Response& response) {
    SetUserDescriptionReq req;
    SetUserDescriptionRsp rsp;

    do {
        // 1. 解析请求参数
        std::string body = request.body;
        if (!req.ParseFromString(body)) {
            LOG_ERROR("设置用户描述请求反序列化失败");
            rsp.set_success(false);
            rsp.set_errmsg("设置用户描述请求反序列化失败");

            break;
        }

        // 2. 查看会话信息是否存在
        const std::string& session_id = req.session_id();
        auto user_id = redis_session_->uid(session_id);
        if (!user_id) {
            LOG_ERROR("[{}] 会话信息不存在", session_id);
            rsp.set_success(false);
            rsp.set_errmsg("会话信息不存在");

            break;
        }
        req.set_user_id(*user_id);

        // 2. 进行RPC调用
        auto channel =
            service_manager_->choose(user_service_name_);  // 获取通信信道
        if (channel == nullptr) {
            LOG_ERROR("获取用户服务通信信道失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取用户服务通信信道失败");

            break;
        }

        brpc::Controller cntl;
        chat::UserService_Stub stub(channel.get());
        stub.SetUserDescription(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed()) {
            LOG_ERROR("设置用户描述RPC调用失败");
            rsp.set_success(false);
            rsp.set_errmsg("设置用户描述RPC调用失败");

            break;
        }
    } while (0);

    response.set_content(rsp.SerializeAsString(), "application/x-probuf");
}

void GatewayServer::handleSetPhone(const httplib::Request& request,
                                   httplib::Response& response) {
    SetUserPhoneNumberReq req;
    SetUserPhoneNumberRsp rsp;

    do {
        // 1. 解析请求参数
        std::string body = request.body;
        if (!req.ParseFromString(body)) {
            LOG_ERROR("设置用户手机号请求反序列化失败");
            rsp.set_success(false);
            rsp.set_errmsg("设置用户手机号请求反序列化失败");

            break;
        }

        // 2. 查看会话信息是否存在
        const std::string& session_id = req.session_id();
        auto user_id = redis_session_->uid(session_id);
        if (!user_id) {
            LOG_ERROR("[{}] 会话信息不存在", session_id);
            rsp.set_success(false);
            rsp.set_errmsg("会话信息不存在");

            break;
        }
        req.set_user_id(*user_id);

        // 2. 进行RPC调用
        auto channel =
            service_manager_->choose(user_service_name_);  // 获取通信信道
        if (channel == nullptr) {
            LOG_ERROR("获取用户服务通信信道失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取用户服务通信信道失败");

            break;
        }

        brpc::Controller cntl;
        chat::UserService_Stub stub(channel.get());
        stub.SetUserPhoneNumber(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed()) {
            LOG_ERROR("设置用户手机号RPC调用失败");
            rsp.set_success(false);
            rsp.set_errmsg("设置用户手机号RPC调用失败");

            break;
        }
    } while (0);

    response.set_content(rsp.SerializeAsString(), "application/x-probuf");
}

void GatewayServer::handleGetFriendList(const httplib::Request& request,
                                        httplib::Response& response) {
    GetFriendListReq req;
    GetFriendListRsp rsp;

    do {
        // 1. 解析请求参数
        std::string body = request.body;
        if (!req.ParseFromString(body)) {
            LOG_ERROR("获取好友列表请求反序列化失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取好友列表请求反序列化失败");

            break;
        }

        // 2. 查看会话信息是否存在
        const std::string& session_id = req.session_id();
        auto user_id = redis_session_->uid(session_id);
        if (!user_id) {
            LOG_ERROR("[{}] 会话信息不存在", session_id);
            rsp.set_success(false);
            rsp.set_errmsg("会话信息不存在");

            break;
        }
        req.set_user_id(*user_id);

        // 2. 进行RPC调用
        auto channel =
            service_manager_->choose(friend_service_name_);  // 获取通信信道
        if (channel == nullptr) {
            LOG_ERROR("获取好友服务通信信道失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取好友服务通信信道失败");

            break;
        }

        brpc::Controller cntl;
        chat::FriendService_Stub stub(channel.get());
        stub.GetFriendList(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed()) {
            LOG_ERROR("获取好友列表RPC调用失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取好友列表RPC调用失败");

            break;
        }
    } while (0);

    response.set_content(rsp.SerializeAsString(), "application/x-probuf");
}

void GatewayServer::handleAddFriend(const httplib::Request& request,
                                    httplib::Response& response) {
    FriendAddReq req;
    FriendAddRsp rsp;

    do {
        // 1. 解析请求参数
        std::string body = request.body;
        if (!req.ParseFromString(body)) {
            LOG_ERROR("发送好友添加请求 请求反序列化失败");
            rsp.set_success(false);
            rsp.set_errmsg("发送好友添加请求 请求反序列化失败");

            break;
        }

        // 2. 查看会话信息是否存在
        const std::string& session_id = req.session_id();
        auto user_id = redis_session_->uid(session_id);
        if (!user_id) {
            LOG_ERROR("[{}] 会话信息不存在", session_id);
            rsp.set_success(false);
            rsp.set_errmsg("会话信息不存在");

            break;
        }
        req.set_user_id(*user_id);

        // 2. 进行RPC调用
        auto channel =
            service_manager_->choose(friend_service_name_);  // 获取通信信道
        if (channel == nullptr) {
            LOG_ERROR("获取好友服务通信信道失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取好友服务通信信道失败");

            break;
        }

        brpc::Controller cntl;
        chat::FriendService_Stub stub(channel.get());
        stub.FriendAdd(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed()) {
            LOG_ERROR("发送好友添加请求 RPC调用失败");
            rsp.set_success(false);
            rsp.set_errmsg("发送好友添加请求 RPC调用失败");

            break;
        }

        server_t::connection_ptr conn =
            connections_.connection(req.respondent_id());
        if (rsp.success() && conn) {
            NotifyMessage notify_msg;
            notify_msg.set_notify_event_id(rsp.notify_event_id());
            notify_msg.set_notify_type(NotifyType::FRIEND_ADD_APPLY_NOTIFY);

            UserInfo user_info;
            if (!getUserInfo(*user_id, &user_info)) {
                LOG_ERROR("获取用户信息[{}] 失败", *user_id);
                rsp.set_success(false);
                rsp.set_errmsg("获取用户信息失败");

                break;
            }

            notify_msg.mutable_friend_add_apply()
                ->mutable_user_info()
                ->CopyFrom(user_info);

            conn->send(notify_msg.SerializeAsString(),
                       websocketpp::frame::opcode::value::binary);
        }
    } while (0);

    response.set_content(rsp.SerializeAsString(), "application/x-probuf");
}

void GatewayServer::handleAddFriendProcess(const httplib::Request& request,
                                           httplib::Response& response) {
    FriendAddProcessReq req;
    FriendAddProcessRsp rsp;

    do {
        // 1. 解析请求参数
        std::string body = request.body;
        if (!req.ParseFromString(body)) {
            LOG_ERROR("好友添加处理请求 请求反序列化失败");
            rsp.set_success(false);
            rsp.set_errmsg("好友添加处理请求 请求反序列化失败");

            break;
        }

        // 2. 查看会话信息是否存在
        const std::string& session_id = req.session_id();
        auto user_id = redis_session_->uid(session_id);
        if (!user_id) {
            LOG_ERROR("[{}] 会话信息不存在", session_id);
            rsp.set_success(false);
            rsp.set_errmsg("会话信息不存在");

            break;
        }
        req.set_user_id(*user_id);

        // 2. 进行RPC调用
        auto channel =
            service_manager_->choose(friend_service_name_);  // 获取通信信道
        if (channel == nullptr) {
            LOG_ERROR("获取好友服务通信信道失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取好友服务通信信道失败");

            break;
        }

        brpc::Controller cntl;
        chat::FriendService_Stub stub(channel.get());
        stub.FriendAddProcess(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed()) {
            LOG_ERROR("好友添加处理请求 RPC调用失败");
            rsp.set_success(false);
            rsp.set_errmsg("好友添加处理请求 RPC调用失败");

            break;
        }

        // 3.对申请人发送好友添加处理结果通知
        if (rsp.success()) {
            // 申请人对应的客户端长连接
            server_t::connection_ptr conn_apply =
                connections_.connection(req.apply_user_id());
            // 被申请人对应的客户端长连接
            server_t::connection_ptr conn_resp =
                connections_.connection(*user_id);

            UserInfo user_info;
            if (!getUserInfo(*user_id, &user_info)) {
                LOG_ERROR("获取被申请人用户信息[{}] 失败", *user_id);
                rsp.set_success(false);
                rsp.set_errmsg("获取被申请人用户信息失败");

                break;
            }

            UserInfo apply_user_info;
            if (!getUserInfo(req.apply_user_id(), &apply_user_info)) {
                LOG_ERROR("获取申请人用户信息[{}] 失败", req.apply_user_id());
                rsp.set_success(false);
                rsp.set_errmsg("获取申请人用户信息失败");

                break;
            }
            if (conn_apply) {
                NotifyMessage notify_msg;
                notify_msg.set_notify_event_id(req.notify_event_id());
                notify_msg.set_notify_type(
                    NotifyType::FRIEND_ADD_PROCESS_NOTIFY);

                auto process_res = notify_msg.mutable_friend_process_result();
                process_res->mutable_user_info()->CopyFrom(user_info);
                process_res->set_agree(req.agree());

                conn_apply->send(notify_msg.SerializeAsString(),
                                 websocketpp::frame::opcode::value::binary);
            }

            // 4. 对申请人发送单聊会话创建通知
            if (conn_apply && req.agree()) {
                NotifyMessage notify_msg;
                notify_msg.set_notify_event_id(req.notify_event_id());
                notify_msg.set_notify_type(
                    NotifyType::CHAT_SESSION_CREATE_NOTIFY);

                auto chat_session_info =
                    notify_msg.mutable_new_chat_session_info()
                        ->mutable_chat_session_info();
                chat_session_info->set_chat_session_id(rsp.new_session_id());
                chat_session_info->set_single_chat_friend_id(*user_id);
                chat_session_info->set_chat_session_name(user_info.nickname());
                chat_session_info->set_avatar(user_info.avatar());

                conn_apply->send(notify_msg.SerializeAsString(),
                                 websocketpp::frame::opcode::value::binary);
            }

            // 5. 对被申请人发送单聊会话创建通知
            if (conn_resp && req.agree()) {
                NotifyMessage notify_msg;
                notify_msg.set_notify_event_id(req.notify_event_id());
                notify_msg.set_notify_type(
                    NotifyType::CHAT_SESSION_CREATE_NOTIFY);

                auto chat_session_info =
                    notify_msg.mutable_new_chat_session_info()
                        ->mutable_chat_session_info();
                chat_session_info->set_chat_session_id(rsp.new_session_id());
                chat_session_info->set_single_chat_friend_id(
                    req.apply_user_id());
                chat_session_info->set_chat_session_name(
                    apply_user_info.nickname());
                chat_session_info->set_avatar(apply_user_info.avatar());

                conn_resp->send(notify_msg.SerializeAsString(),
                                websocketpp::frame::opcode::value::binary);
            }
        }

    } while (0);

    response.set_content(rsp.SerializeAsString(), "application/x-probuf");
}

void GatewayServer::handleRemoveFriend(const httplib::Request& request,
                                       httplib::Response& response) {
    FriendRemoveReq req;
    FriendRemoveRsp rsp;

    do {
        // 1. 解析请求参数
        std::string body = request.body;
        if (!req.ParseFromString(body)) {
            LOG_ERROR("发送好友删除请求 请求反序列化失败");
            rsp.set_success(false);
            rsp.set_errmsg("发送好友删除请求 请求反序列化失败");

            break;
        }

        // 2. 查看会话信息是否存在
        const std::string& session_id = req.session_id();
        auto user_id = redis_session_->uid(session_id);
        if (!user_id) {
            LOG_ERROR("[{}] 会话信息不存在", session_id);
            rsp.set_success(false);
            rsp.set_errmsg("会话信息不存在");

            break;
        }
        req.set_user_id(*user_id);

        // 2. 进行RPC调用
        auto channel =
            service_manager_->choose(friend_service_name_);  // 获取通信信道
        if (channel == nullptr) {
            LOG_ERROR("获取好友服务通信信道失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取好友服务通信信道失败");

            break;
        }

        brpc::Controller cntl;
        chat::FriendService_Stub stub(channel.get());
        stub.FriendRemove(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed()) {
            LOG_ERROR("发送好友删除请求 RPC调用失败");
            rsp.set_success(false);
            rsp.set_errmsg("发送好友删除请求 RPC调用失败");

            break;
        }

        server_t::connection_ptr conn = connections_.connection(req.peer_id());
        if (rsp.success() && conn) {
            NotifyMessage notify_msg;
            notify_msg.set_notify_type(NotifyType::FRIEND_REMOVE_NOTIFY);
            notify_msg.mutable_friend_remove()->set_user_id(*user_id);

            conn->send(notify_msg.SerializeAsString(),
                       websocketpp::frame::opcode::value::binary);
        }
    } while (0);

    response.set_content(rsp.SerializeAsString(), "application/x-probuf");
}

void GatewayServer::handleSearchFriend(const httplib::Request& request,
                                       httplib::Response& response) {
    FriendSearchReq req;
    FriendSearchRsp rsp;

    do {
        // 1. 解析请求参数
        std::string body = request.body;
        if (!req.ParseFromString(body)) {
            LOG_ERROR("发送好友搜索请求 请求反序列化失败");
            rsp.set_success(false);
            rsp.set_errmsg("发送好友搜索请求 请求反序列化失败");

            break;
        }

        // 2. 查看会话信息是否存在
        const std::string& session_id = req.session_id();
        auto user_id = redis_session_->uid(session_id);
        if (!user_id) {
            LOG_ERROR("[{}] 会话信息不存在", session_id);
            rsp.set_success(false);
            rsp.set_errmsg("会话信息不存在");

            break;
        }
        req.set_user_id(*user_id);

        // 2. 进行RPC调用
        auto channel =
            service_manager_->choose(friend_service_name_);  // 获取通信信道
        if (channel == nullptr) {
            LOG_ERROR("获取好友服务通信信道失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取好友服务通信信道失败");

            break;
        }

        brpc::Controller cntl;
        chat::FriendService_Stub stub(channel.get());
        stub.FriendSearch(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed()) {
            LOG_ERROR("发送好友搜索请求 RPC调用失败");
            rsp.set_success(false);
            rsp.set_errmsg("发送好友搜索请求 RPC调用失败");

            break;
        }

    } while (0);

    response.set_content(rsp.SerializeAsString(), "application/x-probuf");
}

void GatewayServer::handleGetChatSessionList(const httplib::Request& request,
                                             httplib::Response& response) {
    GetChatSessionListReq req;
    GetChatSessionListRsp rsp;

    do {
        // 1. 解析请求参数
        std::string body = request.body;
        if (!req.ParseFromString(body)) {
            LOG_ERROR("获取会话列表请求 请求反序列化失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取会话列表请求 请求反序列化失败");

            break;
        }

        // 2. 查看会话信息是否存在
        const std::string& session_id = req.session_id();
        auto user_id = redis_session_->uid(session_id);
        if (!user_id) {
            LOG_ERROR("[{}] 会话信息不存在", session_id);
            rsp.set_success(false);
            rsp.set_errmsg("会话信息不存在");

            break;
        }
        req.set_user_id(*user_id);

        // 2. 进行RPC调用
        auto channel =
            service_manager_->choose(friend_service_name_);  // 获取通信信道
        if (channel == nullptr) {
            LOG_ERROR("获取好友服务通信信道失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取好友服务通信信道失败");

            break;
        }

        brpc::Controller cntl;
        chat::FriendService_Stub stub(channel.get());
        stub.GetChatSessionList(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed()) {
            LOG_ERROR("获取会话列表请求 RPC调用失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取会话列表请求 RPC调用失败");

            break;
        }

    } while (0);

    response.set_content(rsp.SerializeAsString(), "application/x-probuf");
}

void GatewayServer::handleGetChatSessionMember(const httplib::Request& request,
                                               httplib::Response& response) {
    GetChatSessionMemberReq req;
    GetChatSessionMemberRsp rsp;

    do {
        // 1. 解析请求参数
        std::string body = request.body;
        if (!req.ParseFromString(body)) {
            LOG_ERROR("获取会话成员请求 请求反序列化失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取会话成员请求 请求反序列化失败");

            break;
        }

        // 2. 查看会话信息是否存在
        const std::string& session_id = req.session_id();
        auto user_id = redis_session_->uid(session_id);
        if (!user_id) {
            LOG_ERROR("[{}] 会话信息不存在", session_id);
            rsp.set_success(false);
            rsp.set_errmsg("会话信息不存在");

            break;
        }
        req.set_user_id(*user_id);

        // 2. 进行RPC调用
        auto channel =
            service_manager_->choose(friend_service_name_);  // 获取通信信道
        if (channel == nullptr) {
            LOG_ERROR("获取好友服务通信信道失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取好友服务通信信道失败");

            break;
        }

        brpc::Controller cntl;
        chat::FriendService_Stub stub(channel.get());
        stub.GetChatSessionMember(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed()) {
            LOG_ERROR("获取会话成员请求 RPC调用失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取会话成员请求 RPC调用失败");

            break;
        }

    } while (0);

    response.set_content(rsp.SerializeAsString(), "application/x-probuf");
}

void GatewayServer::handleGetPendingFriendEvents(
    const httplib::Request& request, httplib::Response& response) {
    GetPendingFriendEventListReq req;
    GetPendingFriendEventListRsp rsp;

    do {
        // 1. 解析请求参数
        std::string body = request.body;
        if (!req.ParseFromString(body)) {
            LOG_ERROR("获取好友事件列表请求 请求反序列化失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取好友事件列表请求 请求反序列化失败");

            break;
        }

        // 2. 查看会话信息是否存在
        const std::string& session_id = req.session_id();
        auto user_id = redis_session_->uid(session_id);
        if (!user_id) {
            LOG_ERROR("[{}] 会话信息不存在", session_id);
            rsp.set_success(false);
            rsp.set_errmsg("会话信息不存在");

            break;
        }
        req.set_user_id(*user_id);

        // 2. 进行RPC调用
        auto channel =
            service_manager_->choose(friend_service_name_);  // 获取通信信道
        if (channel == nullptr) {
            LOG_ERROR("获取好友服务通信信道失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取好友服务通信信道失败");

            break;
        }

        brpc::Controller cntl;
        chat::FriendService_Stub stub(channel.get());
        stub.GetPendingFriendEventList(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed()) {
            LOG_ERROR("获取好友事件列表请求 RPC调用失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取好友事件列表请求 RPC调用失败");

            break;
        }

    } while (0);

    response.set_content(rsp.SerializeAsString(), "application/x-probuf");
}

void GatewayServer::handleCreateChatSession(const httplib::Request& request,
                                            httplib::Response& response) {
    ChatSessionCreateReq req;
    ChatSessionCreateRsp rsp;

    do {
        // 1. 解析请求参数
        std::string body = request.body;
        if (!req.ParseFromString(body)) {
            LOG_ERROR("创建会话请求 请求反序列化失败");
            rsp.set_success(false);
            rsp.set_errmsg("创建会话请求 请求反序列化失败");

            break;
        }

        // 2. 查看会话信息是否存在
        const std::string& session_id = req.session_id();
        auto user_id = redis_session_->uid(session_id);
        if (!user_id) {
            LOG_ERROR("[{}] 会话信息不存在", session_id);
            rsp.set_success(false);
            rsp.set_errmsg("会话信息不存在");

            break;
        }
        req.set_user_id(*user_id);

        // 2. 进行RPC调用
        auto channel =
            service_manager_->choose(friend_service_name_);  // 获取通信信道
        if (channel == nullptr) {
            LOG_ERROR("获取好友服务通信信道失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取好友服务通信信道失败");

            break;
        }

        brpc::Controller cntl;
        chat::FriendService_Stub stub(channel.get());
        stub.ChatSessionCreate(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed()) {
            LOG_ERROR("创建会话请求 RPC调用失败");
            rsp.set_success(false);
            rsp.set_errmsg("创建会话请求 RPC调用失败");

            break;
        }

        if (rsp.success()) {
            // 3. 向所有的会话成员发送会话创建通知
            for (auto& member_id : req.member_id_list()) {
                server_t::connection_ptr conn =
                    connections_.connection(member_id);
                if (conn) {
                    NotifyMessage notify_msg;
                    notify_msg.set_notify_type(
                        NotifyType::CHAT_SESSION_CREATE_NOTIFY);
                    notify_msg.mutable_new_chat_session_info()
                        ->mutable_chat_session_info()
                        ->CopyFrom(rsp.chat_session_info());

                    conn->send(notify_msg.SerializeAsString(),
                               websocketpp::frame::opcode::value::binary);
                }
            }
        }

    } while (0);

    rsp.clear_chat_session_info();  // 前端不需要这个字段
    response.set_content(rsp.SerializeAsString(), "application/x-probuf");
}

void GatewayServer::handleGetMessageStorageHistory(
    const httplib::Request& request, httplib::Response& response) {
    GetHistoryMsgReq req;
    GetHistoryMsgRsp rsp;

    do {
        // 1. 解析请求参数
        std::string body = request.body;
        if (!req.ParseFromString(body)) {
            LOG_ERROR("获取区间消息消息请求 请求反序列化失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取区间消息消息请求 请求反序列化失败");

            break;
        }

        // 2. 查看会话信息是否存在
        const std::string& session_id = req.session_id();
        auto user_id = redis_session_->uid(session_id);
        if (!user_id) {
            LOG_ERROR("[{}] 会话信息不存在", session_id);
            rsp.set_success(false);
            rsp.set_errmsg("会话信息不存在");

            break;
        }
        req.set_user_id(*user_id);

        // 2. 进行RPC调用
        auto channel =
            service_manager_->choose(message_service_name_);  // 获取通信信道
        if (channel == nullptr) {
            LOG_ERROR("获取消息存储服务通信信道失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取消息存储服务通信信道失败");

            break;
        }

        brpc::Controller cntl;
        chat::MsgStorageService_Stub stub(channel.get());
        stub.GetHistoryMsg(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed()) {
            LOG_ERROR("获取区间消息消息请求 RPC调用失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取区间消息消息请求 RPC调用失败");

            break;
        }

    } while (0);

    response.set_content(rsp.SerializeAsString(), "application/x-probuf");
}

void GatewayServer::handleGetMessageStorageRecent(
    const httplib::Request& request, httplib::Response& response) {
    GetRecentMsgReq req;
    GetRecentMsgRsp rsp;

    do {
        // 1. 解析请求参数
        std::string body = request.body;
        if (!req.ParseFromString(body)) {
            LOG_ERROR("获取最近消息请求 请求反序列化失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取最近消息请求 请求反序列化失败");

            break;
        }

        // 2. 查看会话信息是否存在
        const std::string& session_id = req.session_id();
        auto user_id = redis_session_->uid(session_id);
        if (!user_id) {
            LOG_ERROR("[{}] 会话信息不存在", session_id);
            rsp.set_success(false);
            rsp.set_errmsg("会话信息不存在");

            break;
        }
        req.set_user_id(*user_id);

        // 2. 进行RPC调用
        auto channel =
            service_manager_->choose(message_service_name_);  // 获取通信信道
        if (channel == nullptr) {
            LOG_ERROR("获取消息存储服务通信信道失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取消息存储服务通信信道失败");

            break;
        }

        brpc::Controller cntl;
        chat::MsgStorageService_Stub stub(channel.get());
        stub.GetRecentMsg(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed()) {
            LOG_ERROR("获取最近消息请求 RPC调用失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取最近消息请求 RPC调用失败");

            break;
        }

    } while (0);

    response.set_content(rsp.SerializeAsString(), "application/x-probuf");
}

void GatewayServer::handleSearchMessageStorageHistory(
    const httplib::Request& request, httplib::Response& response) {
    MsgSearchReq req;
    MsgSearchRsp rsp;

    do {
        // 1. 解析请求参数
        std::string body = request.body;
        if (!req.ParseFromString(body)) {
            LOG_ERROR("消息搜索请求 请求反序列化失败");
            rsp.set_success(false);
            rsp.set_errmsg("消息搜索请求 请求反序列化失败");

            break;
        }

        // 2. 查看会话信息是否存在
        const std::string& session_id = req.session_id();
        auto user_id = redis_session_->uid(session_id);
        if (!user_id) {
            LOG_ERROR("[{}] 会话信息不存在", session_id);
            rsp.set_success(false);
            rsp.set_errmsg("会话信息不存在");

            break;
        }
        req.set_user_id(*user_id);

        // 2. 进行RPC调用
        auto channel =
            service_manager_->choose(message_service_name_);  // 获取通信信道
        if (channel == nullptr) {
            LOG_ERROR("获取消息存储服务通信信道失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取消息存储服务通信信道失败");

            break;
        }

        brpc::Controller cntl;
        chat::MsgStorageService_Stub stub(channel.get());
        stub.MsgSearch(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed()) {
            LOG_ERROR("消息搜索请求 RPC调用失败");
            rsp.set_success(false);
            rsp.set_errmsg("消息搜索请求 RPC调用失败");

            break;
        }

    } while (0);

    response.set_content(rsp.SerializeAsString(), "application/x-probuf");
}

void GatewayServer::handleGetSingleFile(const httplib::Request& request,
                                        httplib::Response& response) {
    GetSingleFileReq req;
    GetSingleFileRsp rsp;

    do {
        // 1. 解析请求参数
        std::string body = request.body;
        if (!req.ParseFromString(body)) {
            LOG_ERROR("单个文件下载请求 请求反序列化失败");
            rsp.set_success(false);
            rsp.set_errmsg("单个文件下载请求 请求反序列化失败");

            break;
        }

        // 2. 查看会话信息是否存在
        const std::string& session_id = req.session_id();
        auto user_id = redis_session_->uid(session_id);
        if (!user_id) {
            LOG_ERROR("[{}] 会话信息不存在", session_id);
            rsp.set_success(false);
            rsp.set_errmsg("会话信息不存在");

            break;
        }
        req.set_user_id(*user_id);

        // 2. 进行RPC调用
        auto channel =
            service_manager_->choose(file_service_name_);  // 获取通信信道
        if (channel == nullptr) {
            LOG_ERROR("获取消息存储服务通信信道失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取消息存储服务通信信道失败");

            break;
        }

        brpc::Controller cntl;
        chat::FileService_Stub stub(channel.get());
        stub.GetSingleFile(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed()) {
            LOG_ERROR("单个文件下载请求 RPC调用失败");
            rsp.set_success(false);
            rsp.set_errmsg("单个文件下载请求 RPC调用失败");

            break;
        }

    } while (0);

    response.set_content(rsp.SerializeAsString(), "application/x-probuf");
}

void GatewayServer::handleGetMultiFile(const httplib::Request& request,
                                       httplib::Response& response) {
    GetMultiFileReq req;
    GetMultiFileRsp rsp;

    do {
        // 1. 解析请求参数
        std::string body = request.body;
        if (!req.ParseFromString(body)) {
            LOG_ERROR("批量文件下载请求 请求反序列化失败");
            rsp.set_success(false);
            rsp.set_errmsg("批量文件下载请求 请求反序列化失败");

            break;
        }

        // 2. 查看会话信息是否存在
        const std::string& session_id = req.session_id();
        auto user_id = redis_session_->uid(session_id);
        if (!user_id) {
            LOG_ERROR("[{}] 会话信息不存在", session_id);
            rsp.set_success(false);
            rsp.set_errmsg("会话信息不存在");

            break;
        }
        req.set_user_id(*user_id);

        // 2. 进行RPC调用
        auto channel =
            service_manager_->choose(file_service_name_);  // 获取通信信道
        if (channel == nullptr) {
            LOG_ERROR("获取消息存储服务通信信道失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取消息存储服务通信信道失败");

            break;
        }

        brpc::Controller cntl;
        chat::FileService_Stub stub(channel.get());
        stub.GetMultiFile(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed()) {
            LOG_ERROR("批量文件下载请求 RPC调用失败");
            rsp.set_success(false);
            rsp.set_errmsg("批量文件下载请求 RPC调用失败");

            break;
        }

    } while (0);

    response.set_content(rsp.SerializeAsString(), "application/x-probuf");
}

void GatewayServer::handlePutSingleFile(const httplib::Request& request,
                                        httplib::Response& response) {
    PutSingleFileReq req;
    PutSingleFileRsp rsp;

    do {
        // 1. 解析请求参数
        std::string body = request.body;
        if (!req.ParseFromString(body)) {
            LOG_ERROR("单个文件上传请求 请求反序列化失败");
            rsp.set_success(false);
            rsp.set_errmsg("单个文件上传请求 请求反序列化失败");

            break;
        }

        // 2. 查看会话信息是否存在
        const std::string& session_id = req.session_id();
        auto user_id = redis_session_->uid(session_id);
        if (!user_id) {
            LOG_ERROR("[{}] 会话信息不存在", session_id);
            rsp.set_success(false);
            rsp.set_errmsg("会话信息不存在");

            break;
        }
        req.set_user_id(*user_id);

        // 2. 进行RPC调用
        auto channel =
            service_manager_->choose(file_service_name_);  // 获取通信信道
        if (channel == nullptr) {
            LOG_ERROR("获取消息存储服务通信信道失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取消息存储服务通信信道失败");

            break;
        }

        brpc::Controller cntl;
        chat::FileService_Stub stub(channel.get());
        stub.PutSingleFile(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed()) {
            LOG_ERROR("单个文件上传请求 RPC调用失败");
            rsp.set_success(false);
            rsp.set_errmsg("单个文件上传请求 RPC调用失败");

            break;
        }

    } while (0);

    response.set_content(rsp.SerializeAsString(), "application/x-probuf");
}

void GatewayServer::handlePutMultiFile(const httplib::Request& request,
                                       httplib::Response& response) {
    PutMultiFileReq req;
    PutMultiFileRsp rsp;

    do {
        // 1. 解析请求参数
        std::string body = request.body;
        if (!req.ParseFromString(body)) {
            LOG_ERROR("批量文件上传请求 请求反序列化失败");
            rsp.set_success(false);
            rsp.set_errmsg("批量文件上传请求 请求反序列化失败");

            break;
        }

        // 2. 查看会话信息是否存在
        const std::string& session_id = req.session_id();
        auto user_id = redis_session_->uid(session_id);
        if (!user_id) {
            LOG_ERROR("[{}] 会话信息不存在", session_id);
            rsp.set_success(false);
            rsp.set_errmsg("会话信息不存在");

            break;
        }
        req.set_user_id(*user_id);

        // 2. 进行RPC调用
        auto channel =
            service_manager_->choose(file_service_name_);  // 获取通信信道
        if (channel == nullptr) {
            LOG_ERROR("获取消息存储服务通信信道失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取消息存储服务通信信道失败");

            break;
        }

        brpc::Controller cntl;
        chat::FileService_Stub stub(channel.get());
        stub.PutMultiFile(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed()) {
            LOG_ERROR("批量文件上传请求 RPC调用失败");
            rsp.set_success(false);
            rsp.set_errmsg("批量文件上传请求 RPC调用失败");

            break;
        }

    } while (0);

    response.set_content(rsp.SerializeAsString(), "application/x-probuf");
}

void GatewayServer::handleSpeechRecognition(const httplib::Request& request,
                                            httplib::Response& response) {
    SpeechRecognitionReq req;
    SpeechRecognitionRsp rsp;

    do {
        // 1. 解析请求参数
        std::string body = request.body;
        if (!req.ParseFromString(body)) {
            LOG_ERROR("语音识别请求 请求反序列化失败");
            rsp.set_success(false);
            rsp.set_errmsg("语音识别请求 请求反序列化失败");

            break;
        }

        // 2. 查看会话信息是否存在
        const std::string& session_id = req.session_id();
        auto user_id = redis_session_->uid(session_id);
        if (!user_id) {
            LOG_ERROR("[{}] 会话信息不存在", session_id);
            rsp.set_success(false);
            rsp.set_errmsg("会话信息不存在");

            break;
        }
        req.set_user_id(*user_id);

        // 2. 进行RPC调用
        auto channel =
            service_manager_->choose(speech_service_name_);  // 获取通信信道
        if (channel == nullptr) {
            LOG_ERROR("获取语音识别服务通信信道失败");
            rsp.set_success(false);
            rsp.set_errmsg("获取语音识别服务通信信道失败");

            break;
        }

        brpc::Controller cntl;
        chat::SpeechService_Stub stub(channel.get());
        stub.SpeechRecognition(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed()) {
            LOG_ERROR("语音识别请求 RPC调用失败");
            rsp.set_success(false);
            rsp.set_errmsg("语音识别请求 RPC调用失败");

            break;
        }

    } while (0);

    response.set_content(rsp.SerializeAsString(), "application/x-probuf");
}

void GatewayServer::handleNewMessage(const httplib::Request& request,
                                     httplib::Response& response) {
    NewMessageReq req;
    NewMessageRsp rsp;
    GetTransmitTargetRsp target_rsp;

    bool is_success = true;
    std::string err_msg = "OK";

    do {
        // 1. 解析请求参数
        std::string body = request.body;
        if (!req.ParseFromString(body)) {
            LOG_ERROR("新消息请求 请求反序列化失败");
            is_success = false;
            err_msg = "新消息请求 请求反序列化失败";

            break;
        }

        // 2. 查看会话信息是否存在
        const std::string& session_id = req.session_id();
        auto user_id = redis_session_->uid(session_id);
        if (!user_id) {
            LOG_ERROR("[{}] 会话信息不存在", session_id);
            is_success = false;
            err_msg = "会话信息不存在";

            break;
        }
        req.set_user_id(*user_id);

        // 2. 进行RPC调用
        auto channel =
            service_manager_->choose(transmit_service_name_);  // 获取通信信道
        if (channel == nullptr) {
            LOG_ERROR("获取消息转发服务通信信道失败");
            is_success = false;
            err_msg = "获取消息转发服务通信信道失败";

            break;
        }

        brpc::Controller cntl;
        chat::MsgTransmitService_Stub stub(channel.get());
        stub.GetTransmitTarget(&cntl, &req, &target_rsp, nullptr);
        if (cntl.Failed()) {
            LOG_ERROR("新消息请求 RPC调用失败");
            is_success = false;
            err_msg = "新消息请求 RPC调用失败";

            break;
        }

        if (target_rsp.success()) {
            // 3. 向消息转发目标发送新消息通知
            for (auto& target_id : target_rsp.target_id_list()) {
                server_t::connection_ptr conn =
                    connections_.connection(target_id);
                if (conn) {
                    NotifyMessage notify_msg;
                    notify_msg.set_notify_type(NotifyType::CHAT_MESSAGE_NOTIFY);
                    notify_msg.mutable_new_message_info()
                        ->mutable_message_info()
                        ->CopyFrom(target_rsp.message());

                    conn->send(notify_msg.SerializeAsString(),
                               websocketpp::frame::opcode::value::binary);
                }
            }
        }

    } while (0);

    rsp.set_success(is_success);
    rsp.set_errmsg(err_msg);
    rsp.set_request_id(req.request_id());
    response.set_content(rsp.SerializeAsString(), "application/x-probuf");
}

bool GatewayServer::getUserInfo(const std::string& user_id,
                                UserInfo* user_info) {
    GetUserInfoReq req;
    GetUserInfoRsp rsp;
    bool ret = false;

    req.set_request_id(Uuid::uuid());
    req.set_user_id(user_id);

    do {
        // 2. 进行RPC调用
        auto channel =
            service_manager_->choose(user_service_name_);  // 获取通信信道
        if (channel == nullptr) {
            LOG_ERROR("获取用户服务通信信道失败");

            break;
        }

        brpc::Controller cntl;
        chat::UserService_Stub stub(channel.get());
        stub.GetUserInfo(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed()) {
            LOG_ERROR("获取用户信息RPC调用失败");

            break;
        }

        *user_info = rsp.user_info();
        ret = true;
    } while (0);

    return ret;
}

// -------------------------------------------------------------------

// GateWayServerBuilder

void GateWayServerBuilder::makeServiceManager(
    const std::string& file_service_name, const std::string& user_service_name,
    const std::string& speech_service_name,
    const std::string& transmit_service_name,
    const std::string& message_service_name,
    const std::string& friend_service_name) {
    service_manager_ = std::make_shared<ServiceManager>();
    service_manager_->declared(file_service_name);      // 添加关心
    service_manager_->declared(user_service_name);      // 添加关心
    service_manager_->declared(speech_service_name);    // 添加关心
    service_manager_->declared(transmit_service_name);  // 添加关心
    service_manager_->declared(message_service_name);   // 添加关心
    service_manager_->declared(friend_service_name);    // 添加关心

    file_service_name_ = file_service_name;
    user_service_name_ = user_service_name;
    speech_service_name_ = speech_service_name;
    transmit_service_name_ = transmit_service_name;
    message_service_name_ = message_service_name;
    friend_service_name_ = friend_service_name;
}

void GateWayServerBuilder::makeDiscoveryClient(
    const std::string& etcd_host, const std::string& base_service) {
    discovery_client_ = std::make_shared<Discovery>(
        etcd_host, base_service,
        std::bind(&ServiceManager::onServiceOnline, service_manager_.get(),
                  std::placeholders::_1, std::placeholders::_2),
        std::bind(&ServiceManager::onServiceOffline, service_manager_.get(),
                  std::placeholders::_1, std::placeholders::_2));
}

void GateWayServerBuilder::makeRedisClient(const std::string& ip,
                                           const uint16_t port, const int db,
                                           const bool keep_alive) {
    redis_client_ = RedisClientFactory::create(ip, port, db, keep_alive);
}

void GateWayServerBuilder::makeServer(uint16_t ws_port, uint16_t http_port) {
    ws_port_ = ws_port;
    http_port_ = http_port;
}

GatewayServerPtr GateWayServerBuilder::build() {
    if (discovery_client_ == nullptr) {
        LOG_FATAL("服务发现客户端未实例化");
        abort();
    }
    if (redis_client_ == nullptr) {
        LOG_FATAL("Redis 客户端未实例化");
        abort();
    }
    if (service_manager_ == nullptr) {
        LOG_FATAL("服务管理对象 未实例化");
        abort();
    }
    return std::make_shared<GatewayServer>(
        ws_port_, http_port_, redis_client_, service_manager_,
        file_service_name_, user_service_name_, speech_service_name_,
        transmit_service_name_, message_service_name_, friend_service_name_,
        discovery_client_);
}
}  // namespace chat